#!/usr/bin/python
# -*- coding: koi8-r -*-
# $Id: bot.py,v 1.2 2006/10/06 12:30:42 normanr Exp $

import sys
import xmpp
import math
import time

effect_radius = 200              # Km
commands={}
i18n={'ru':{},'en':{}}
users_positions = {}

########################### user handlers start ##################################
i18n['en']['HELP']="This is example jabber bot.\nAvailable commands: %s"
def helpHandler(user,command,args,mess):
    lst=commands.keys()
    lst.sort()
    return "HELP",', '.join(lst)

i18n['en']['EMPTY']="%s"
i18n['en']['HELLOWORLD']='Ola mundo'
def helloworldHandler(user,command,args,mess):
    return "Ola mundo"

i18n['en']['REGISTER_POSITION']='Regiser position'
def register_positionHandler(user,command,args,mess):
    users_positions[user.getStripped()] = float(args[0]), float(args[1])
    update_next_list_all( users_positions )
    
i18n['en']['SHOW_USERS_POSITIONS']='Users positions: %s'
def show_users_positionsHandler(user,command,args,mess):
    return "SHOW_USERS_POSITIONS", '%s'%users_positions

i18n['en']['UPDATE_NEXT_LIST']='%s'
def show_users_positionsHandler(user,command,args,mess):
        
        
    return "SHOW_USERS_POSITIONS", ', '.join(users_positions.keys())

def update_next_list_all( users_positions ):
    for u2up, u2up_pos in users_positions.iteritems():
        next_list = []
        for u2ask, u2ask_pos in users_positions.iteritems():
            if u2up != u2ask and calc_distance( u2up_pos, u2ask_pos ) <= effect_radius:
                next_list.append( u2ask )
        if len(next_list) > 0:
            msg = 'update_next_list ' + " ".join(next_list)
            send_message( u2up, msg )


def calc_distance( posA, posB ):
    posA_lat, posA_long = posA
    posB_lat, posB_long = posB
    
    arc_c = math.radians(90.0 - posB_lat)
    arc_b = math.radians(90.0 - posA_lat)
    arc_a = math.radians(posB_long - posA_long)

    cos_a = (math.cos(arc_b)*math.cos(arc_c)) + (math.sin(arc_b)*math.sin(arc_c)*math.cos(arc_a))
    arc_cos_a =  math.degrees(math.acos(cos_a))
    
    earth_arc_divided = 111.194           # (2*PI*earth_radius)/360

    dist = arc_cos_a * earth_arc_divided

    return dist

def send_message( recv, msg ):
    conn.send(xmpp.Message( recv, msg ) )
    time.sleep(1)

########################### user handlers stop ###################################
############################ bot logic start #####################################
i18n['en']["UNKNOWN COMMAND"]='Unknown command "%s". Try "help"'
i18n['en']["UNKNOWN USER"]="I do not know you. Register first."

def messageCB(conn,mess):
    text=mess.getBody()
    user=mess.getFrom()
    user.lang='en'      # dup
    if text.find(' ')+1:
        command_args=text.split(' ')
        command = command_args[0]
        args = command_args[1:]
    else:
        command,args=text,''
    cmd=command.lower()

    if commands.has_key(cmd): reply=commands[cmd](user,command,args,mess)
    else: reply=("UNKNOWN COMMAND",cmd)

    if type(reply)==type(()):
        key,args=reply
        if i18n[user.lang].has_key(key): pat=i18n[user.lang][key]
        elif i18n['en'].has_key(key): pat=i18n['en'][key]
        else: pat="%s"
        if type(pat)==type(''): reply=pat%args
        else: reply=pat(**args)
    else:
        try: reply=i18n[user.lang][reply]
        except KeyError:
            try: reply=i18n['en'][reply]
            except KeyError: pass
    if reply: conn.send(xmpp.Message(mess.getFrom(),reply))

for i in globals().keys():
    if i[-7:]=='Handler' and i[:-7].lower()==i[:-7]: commands[i[:-7]]=globals()[i]

############################# bot logic stop #####################################

def StepOn(conn):
    try:
        conn.Process(1)
    except KeyboardInterrupt: return 0
    return 1

def GoOn(conn):
    while StepOn(conn): pass

if len(sys.argv)<3:
    print "Usage: bot.py username@server.net password"
else:
    jid=xmpp.JID(sys.argv[1])
    user,server,password=jid.getNode(),jid.getDomain(),sys.argv[2]

    conn=xmpp.Client(server)#,debug=[])
    conres=conn.connect()
    if not conres:
        print "Unable to connect to server %s!"%server
        sys.exit(1)
    if conres<>'tls':
        print "Warning: unable to estabilish secure connection - TLS failed!"
    authres=conn.auth(user,password)
    if not authres:
        print "Unable to authorize on %s - check login/password."%server
        sys.exit(1)
    if authres<>'sasl':
        print "Warning: unable to perform SASL auth os %s. Old authentication method used!"%server
    conn.RegisterHandler('message',messageCB)
    conn.sendInitPresence()
    print "Bot started."
    GoOn(conn)
